﻿#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Admin.Core.Service.sys.Role/SysRoleServiceImpl 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       N/A
* 类 名：       SysRoleServiceImpl
* 创建时间：  2025/6/4 16:09:46
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using DotNetCore.CAP.Dashboard;
using MapsterMapper; 
using SSPivot.Admin.Core.DbModel.sys;
using SSPivot.Admin.Core.Service.sys.Org.Dto;
using SSPivot.Admin.Core.Service.sys.Permission.Dto;
using SSPivot.Admin.Core.Service.sys.Role.Dto;
using SSPivot.AspNetCore.Abstractions.User;
using SSPivot.AspNetCore.Services;
using SSPivot.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using SSPivot.Admin.Core.Repository;
using Mapster;
using Microsoft.EntityFrameworkCore;

namespace SSPivot.Admin.Core.Service.sys.Role
{
    /// <summary>
    /// 角色服务
    /// </summary>
    public class SysRoleServiceImpl : ApplicationService, ISysRoleService
    {
        #region 接口注入
        public ISSPivotRepository<sys_role> SysRoleRep { get; set; }
        public ISSPivotRepository<sys_user> SysUserRep { get; set; }
        public ISSPivotRepository<sys_org> SysOrgRep { get; set; }
        public ISSPivotRepository<sys_user_role> SysUserRoleRep { get; set; }
        public ISSPivotRepository<sys_role_permission> SysRolePermissionRep { get; set; }
        public ISSPivotRepository<sys_role_org> SysRoleOrgRep { get; set; }
        #endregion

        #region 服务


        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<SysRoleDto> GetAsync(long id)
        {
            var data = await SysRoleRep.GetAsync(id);
            var result = data.Adapt<SysRoleDto>();
            var orgData = await SysOrgRep.Query().ToListAsync();
            result.Orgs = orgData.Adapt<List<SysOrgDto>>();
            return result;
        }

        /// <summary>
        /// 查询列表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<List<RoleGetListDto>> GetListAsync(QuerySysRoleRequest model)
        {
            var data = await SysRoleRep.QueryNoTracking(this.BuildSearch(model), this.BuildSort(model)).ToListAsync();
            return data.Adapt<List<RoleGetListDto>>();
        }

        /// <summary>
        /// 查询分页
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns> 
        public async Task<(List<RoleGetPageDto>, PageResult)> GetPageAsync(QuerySysRoleRequest model, PageResult page)
        {
            var data = await SysRoleRep.QueryNoTracking(this.BuildSearch(model), this.BuildSort(model), page).ToListAsync();
            return (data.Adapt<List<RoleGetPageDto>>(), page);
        }

        /// <summary>
        /// 查询角色用户列表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<List<RoleGetUserListDto>> GetRoleUserListAsync(QueryRoleGetUserRequset model)
        {
            var roleIds = await SysUserRoleRep.QueryNoTracking(e => e.RoleId == model.RoleId).Select(e => e.UserId).ToListAsync();
            var query = SysUserRep.QueryNoTracking(e => roleIds.Contains(e.Id));
            if (model.Name.IsNotNullOrWhiteSpace()) query = query.Where(e => e.Name.Contains(model.Name));
            var data = await query.OrderByDescending(e => e.Id).ToListAsync();
            return data.Adapt<List<RoleGetUserListDto>>();
        }

        /// <summary>
        /// 添加角色用户
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task AddRoleUserAsync(RoleAddUserListDto model)
        {
            var roleId = model.RoleId;
            var userIds = await SysUserRoleRep.QueryNoTracking(a => a.RoleId == roleId).Select(a => a.UserId).ToListAsync();
            var insertUserIds = model.UserIds.Except(userIds);
            if (insertUserIds != null && insertUserIds.Any())
            {
                var userRoleList = insertUserIds.Select(userId => new sys_user_role
                {
                    UserId = userId,
                    RoleId = roleId
                }).ToList();
                await SysUserRoleRep.AddRangeAsync(userRoleList);
            }

            var clearUserIds = userIds.Concat(model.UserIds).Distinct();
            foreach (var userId in clearUserIds)
            {
                await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.GetDataPermissionPattern(userId));
            }
        }

        /// <summary>
        /// 移除角色用户
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns> 
        public async Task RemoveRoleUserAsync(RoleAddUserListDto model)
        {
            var userIds = model.UserIds;
            if (userIds != null && userIds.Any())
            {
                await SysUserRoleRep.QueryIgnoreQueryFilters(a => a.RoleId == model.RoleId && model.UserIds.Contains(a.UserId)).ExecuteDeleteAsync();
            }

            foreach (var userId in userIds)
            {
                await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.GetDataPermissionPattern(userId));
            }
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<long> AddAsync(SysRoleDto model)
        {
            if (await SysRoleRep.QueryNoTracking(a => a.ParentId == model.ParentId && a.Name == model.Name).AnyAsync())
            {
                throw ServiceResult.Exception(string.Format("此{0}已存在", model.Type == RoleType.Group ? "分组" : "角色"));
            }

            if (model.Code.IsNotNullOrEmpty() && await SysRoleRep.QueryNoTracking(a => a.ParentId == model.ParentId && a.Code == model.Code).AnyAsync())
            {
                throw ServiceResult.Exception(string.Format("此{0}编码已存在", model.Type == RoleType.Group ? "分组" : "角色"));
            }

            var entity = Mapper.Map<sys_role>(model);
            if (entity.Sort == 0)
            {
                var sort = await SysRoleRep.QueryNoTracking(a => a.ParentId == model.ParentId).MaxAsync(a => a.Sort);
                entity.Sort = sort + 1;
            }
            await SetParentsValue(entity);
            await SysRoleRep.AddAsync(entity);
            if (model.DataScope == DataScope.Custom)
            {
                await AddRoleOrgAsync(entity.Id, model.OrgIds);
            }

            return entity.Id;
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task UpdateAsync(SysRoleDto model)
        {
            var entity = await SysRoleRep.GetAsync(model.Id);
            if (!(entity?.Id > 0))
            {
                throw ServiceResult.Exception("角色不存在");
            }

            if (await SysRoleRep.QueryNoTracking(a => a.ParentId == model.ParentId && a.Id != model.Id && a.Name == model.Name).AnyAsync())
            {
                throw ServiceResult.Exception(string.Format("此{0}已存在", model.Type == RoleType.Group ? "分组" : "角色"));
            }

            if (model.Code.IsNotNullOrEmpty() && await SysRoleRep.QueryNoTracking(a => a.ParentId == model.ParentId && a.Id != model.Id && a.Code == model.Code).AnyAsync())
            {
                throw ServiceResult.Exception(string.Format("此{0}编码已存在", model.Type == RoleType.Group ? "分组" : "角色"));
            }

            Mapper.Map(model, entity);
            await SetParentsValue(entity);
            await SysRoleRep.UpdateAsync(entity);
            await SysRoleOrgRep.Query(a => a.RoleId == entity.Id).ExecuteDeleteAsync();
            if (model.DataScope == DataScope.Custom)
            {
                await AddRoleOrgAsync(entity.Id, model.OrgIds);
            }

            var userIds = await SysUserRoleRep.QueryNoTracking(a => a.RoleId == entity.Id).Select(a => a.UserId).ToListAsync();
            foreach (var userId in userIds)
            {
                await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.GetDataPermissionPattern(userId));
            }
        }

        /// <summary>
        /// 彻底删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns> 
        public virtual async Task DeleteAsync(long id)
        {
            var roleIdList = await this.GetChildrenIdListAsync(id);
            var userIds = await SysUserRoleRep.QueryNoTracking(a => roleIdList.Contains(a.RoleId)).Select(a => a.UserId).ToListAsync();

            //删除用户角色
            await SysUserRoleRep.QueryIgnoreQueryFilters(a => a.UserId == id).ExecuteDeleteAsync();
            //删除角色权限
            await SysRolePermissionRep.QueryIgnoreQueryFilters(a => roleIdList.Contains(a.RoleId)).ExecuteDeleteAsync();
            //删除角色
            await SysRoleRep.QueryIgnoreQueryFilters(a => roleIdList.Contains(a.Id)).ExecuteDeleteAsync();

            foreach (var userId in userIds)
            {
                await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.GetDataPermissionPattern(userId));
            }
        }

        /// <summary>
        /// 批量彻底删除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>       
        public virtual async Task BatchDeleteAsync(long[] ids)
        {
            var roleIdList = new List<long>();
            foreach (var item in ids)
            {
                roleIdList.AddRange(await this.GetChildrenIdListAsync(item));
            }
            var userIds = await SysUserRoleRep.QueryNoTracking(a => roleIdList.Contains(a.RoleId)).Select(a => a.UserId).ToListAsync();

            //删除用户角色
            await SysUserRoleRep.QueryIgnoreQueryFilters(a => roleIdList.Contains(a.RoleId)).ExecuteDeleteAsync();
            //删除角色权限
            await SysRolePermissionRep.QueryIgnoreQueryFilters(a => roleIdList.Contains(a.RoleId)).ExecuteDeleteAsync();
            //删除角色
            await SysRoleRep.QueryIgnoreQueryFilters(a => roleIdList.Contains(a.Id)).ExecuteDeleteAsync();

            foreach (var userId in userIds)
            {
                await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.GetDataPermissionPattern(userId));
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>     
        public virtual async Task SoftDeleteAsync(long id)
        {
            var roleIdList = await this.GetChildrenIdListAsync(id);
            var userIds = await SysUserRoleRep.QueryNoTracking(a => roleIdList.Contains(a.RoleId)).Select(a => a.UserId).ToListAsync();
            await SysUserRoleRep.Query(a => roleIdList.Contains(a.RoleId)).ExecuteDeleteAsync();
            await SysRolePermissionRep.Query(a => roleIdList.Contains(a.RoleId)).ExecuteDeleteAsync();
            await SysRoleRep.Query(a => roleIdList.Contains(a.Id)).ExecuteDeleteAsync();
            foreach (var userId in userIds)
            {
                await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.GetDataPermissionPattern(userId));
            }
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>     
        public virtual async Task BatchSoftDeleteAsync(long[] ids)
        {
            var roleIdList = new List<long>();
            foreach (var item in ids)
            {
                roleIdList.AddRange(await this.GetChildrenIdListAsync(item));
            }
            var userIds = await SysUserRoleRep.QueryNoTracking(a => roleIdList.Contains(a.RoleId)).Select(a => a.UserId).ToListAsync();

            await SysUserRoleRep.Query(a => roleIdList.Contains(a.RoleId)).ExecuteDeleteAsync();
            await SysRolePermissionRep.Query(a => roleIdList.Contains(a.RoleId)).ExecuteDeleteAsync();
            await SysRoleRep.Query(a => roleIdList.Contains(a.Id)).ExecuteDeleteAsync();
            foreach (var userId in userIds)
            {
                await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.GetDataPermissionPattern(userId));
            }
        }

        /// <summary>
        /// 设置数据权限
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task SetDataScopeAsync(RoleSetDataScopeDto model)
        {
            var entity = await SysRoleRep.GetAsync(model.RoleId);
            if (!(entity?.Id > 0))
            {
                throw ServiceResult.Exception("角色不存在");
            }

            Mapper.Map(model, entity);
            await SysRoleRep.UpdateAsync(entity);
            await SysRoleOrgRep.QueryIgnoreQueryFilters(a => a.RoleId == entity.Id).ExecuteDeleteAsync();
            if (model.DataScope == DataScope.Custom)
            {
                await AddRoleOrgAsync(entity.Id, model.OrgIds);
            }

            var userIds = await SysUserRoleRep.QueryNoTracking(a => a.RoleId == entity.Id).Select(a => a.UserId).ToListAsync();
            foreach (var userId in userIds)
            {
                await Cache.RemoveAsync(SSPivot.AspNetCore.GlobalConfigAspNetCore.CacheKeys.GetDataPermissionPattern(userId));
            }
        }
        #endregion

        #region tree

        /// <summary>
        /// 获得本级和下级Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<long>> GetChildrenIdListAsync(long id)
        {

            return await SysRoleRep.QueryNoTracking(e => e.ParentIds.Contains(id.ToString())).Select(e => e.Id).ToListAsync();

        }

        /// <summary>
        /// 获取上级
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<List<SysRoleDto>> GetSupCategory(long id)
        {
            var result = new List<SysRoleDto>();
            var current = await this.GetAsync(id);
            if (current != null)
            {
                if (current.ParentId != 0)
                {
                    result.AddRange(await this.GetSupCategory(current.Id.Value));
                }
                result.Add(current);
            }
            return result;
        }

        /// <summary>
        /// 获取上级名称
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        public async Task<List<string>> GetSupCategoryName(long id)
        {
            var data = await this.GetSupCategory(id);
            return data.Select(e => e.Name).ToList();
        }

        /// <summary>
        /// 获取下级部门带层级
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<List<SysRoleDto>> GetSubCategoryTreeAsync(QuerySysRoleRequest model)
        {
            var result = new List<SysRoleDto>();
            var query = SysRoleRep.QueryNoTracking();
            if (model.ParentId.HasValue)
            {
                if (model.ContainSelf)
                    query = query.Where(e => e.Id == model.ParentId);
                else
                    query = query.Where(e => e.ParentId == model.ParentId);
            }
            else
            {
                query = query.Where(e => e.ParentId == 0);
            }
            var data = await query.ToListAsync();
            var listData = data.Adapt<List<SysRoleDto>>();
            var allEntity = await SysRoleRep.QueryNoTracking(e => true, e => e.Sort, SortType.Asc).ToListAsync();
            var allData = allEntity.Adapt<List<SysRoleDto>>();
            foreach (var item in listData)
            {
                result.Add(RecursionCategory(item, allData));
            }
            return result;
        }

        /// <summary>
        /// 获取类别tree
        /// </summary>
        /// <returns></returns>
        public async Task<List<SysRoleDto>> GetAllDataTreeAsync(QuerySysRoleRequest model)
        {
            var allEntity = await SysRoleRep.QueryNoTracking(this.BuildSearch(model), e => e.Sort, SortType.Asc).ToListAsync();
            var allData = allEntity.Adapt<List<SysRoleDto>>();
            var mainData = allData.Where(e => e.ParentId == 0).ToList();
            var result = new List<SysRoleDto>();
            foreach (var item in allData)
            {
                result.Add(RecursionCategory(item, allData));
            }

            return result;
        }
        /// <summary>
        /// 递归获取所有子级部门及层级
        /// </summary>
        /// <param name="model"></param>
        public SysRoleDto RecursionCategory(SysRoleDto model, List<SysRoleDto> allData)
        {
            var childData = allData.Where(e => e.ParentId == model.Id).ToList();
            if (childData != null && childData.Count() > 0)
            {
                if (model.Children == null || model.Children.Count() == 0)
                    model.Children = new List<SysRoleDto>();
                foreach (var child in childData)
                {
                    child.Level = model.Level + 1;
                    model.Children.Add(RecursionCategory(child, allData));
                }

            }
            return model;
        }
        #endregion
        #region private
        /// <summary>
        /// 添加角色部门
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="orgIds"></param>
        /// <returns></returns>
        private async Task AddRoleOrgAsync(long roleId, long[] orgIds)
        {
            if (orgIds != null && orgIds.Any())
            {
                var roleOrgs = orgIds.Select(orgId => new sys_role_org
                {
                    RoleId = roleId,
                    OrgId = orgId
                }).ToList();
                await SysRoleOrgRep.AddRangeAsync(roleOrgs);
            }
        }

        private Expression<Func<sys_role, bool>> BuildSearch(QuerySysRoleRequest model)
        {
            Expression<Func<sys_role, bool>> whereCondition = e => true;

            if (model.Key.IsNotNullOrWhiteSpace())
                whereCondition = whereCondition.And(e => e.Name.Contains(model.Key));
            if (model.SDate.HasValue)
                whereCondition = whereCondition.And(e => e.CreatedTime > model.SDate);
            if (model.EDate.HasValue)
            {
                var date = model.EDate.Value.AddDays(1);
                whereCondition = whereCondition.And(e => e.CreatedTime < date);
            }
            if (model.ParentId.HasValue)
            {
                if (model.ContainSelf)
                    whereCondition = whereCondition.And(e => e.Id == model.ParentId);
                else
                    whereCondition = whereCondition.And(e => e.ParentId == model.ParentId);
            }
            else
            {
                whereCondition = whereCondition.And(e => e.ParentId == 0);
            }
            return whereCondition;
        }

        private Dictionary<Expression<Func<sys_role, dynamic>>, SortType> BuildSort(QuerySysRoleRequest model)
        {
            var orderBy = new Dictionary<Expression<Func<sys_role, dynamic>>, SortType>();
            orderBy.Add(e => e.ParentId, SortType.Asc);
            orderBy.Add(e => e.Sort, SortType.Asc);
            orderBy.Add(e => e.Id, SortType.Desc);
            return orderBy;
        }
        private async Task<sys_role> SetParentsValue(sys_role model)
        {
            if (model.ParentId == 0)
            {
                var pids = new List<long>() { model.Id };
                var names = new List<string>() { model.Name };
                model.ParentId = 0;
                model.ParentIds = pids.SerializeJson();
                model.ParentNames = names.SerializeJson();

            }
            else
            {
                var parent = (await SysRoleRep.QueryNoTracking(x => x.Id == model.ParentId).FirstOrDefaultAsync()).Adapt<SysOrgDto>();
                parent.ParentIds.Add(model.Id);
                model.ParentIds = parent.ParentIds.SerializeJson();
                parent.ParentNames.Add(model.Name);
                model.ParentNames = parent.ParentNames.SerializeJson();
            }
            return model;
        }
        #endregion
    }
}

